; void monocromatizar_uno_asm(unsigned char *src,  	rdi 
			;unsigned char *dst,  		rsi 
			;int h,               		rdx 
			;int w,               		rcx 
			;int src_row_size,    		r8  
			;int dst_row_size)    		r9  

global monocromatizar_uno_asm

section .text

monocromatizar_uno_asm:
	push rbp
	mov rbp, rsp
	push rbx
	push r12
	push r13
	push r14
	push r15		;armo el stack



	xor rax, rax

	mov rax, r8
	sub rax, rcx	
	sub rax, rcx	
	sub rax, rcx	
	xor r10, r10
	mov r10, rax ; en  r10 tengo el desplazamiendo de src

	xor rax, rax

	mov rax, r9	
	sub rax, rcx	
	xor r11, r11
	mov r11, rax ; en r11 tengo el desplazamiento de dst

	xor rax, rax

	mov rax, rcx	
	shr rax, 1
	dec rax
	xor r12, r12
	mov r12, rax	; en  r12 tengo la cantidad de iteraciones por fila

	xor rbx, rbx

	shl rax, 1
	mov rbx, rcx		
	sub rbx, rax
	mov r13, rbx	; en  r13 tengo la cantidad de pixels q no entraron en la iteracion por no ser multiplo de 2
	
	xor rax, rax

	mov eax, 0xffff0000
	movd xmm7, eax
	pslldq xmm7, 4
	mov eax, 0x0000ffff
	movd xmm6, eax
	por xmm7, xmm6
	
	mov eax, 0xffffffff
	movd xmm6, eax
	
	mov eax, 0x000000ff
	movd xmm5, eax
	movsldup xmm5, xmm5
		
	xor rcx, rcx

	mov rcx, rdx		;en ecx tengo la altura




cicloF:


	xor r15, r15
	mov r15, r12		; en r15 tengo la cantidad de it x fila
cicloC:

	pxor xmm4, xmm4
	movdqu xmm0, [rdi]; R1|G1|B1|R2|G2|B2|R3|G3|B3|R4|G4|B4|R5|G5|B5|R6 , cada color ocupa un byte
	punpcklbw xmm0, xmm4; paso de byte a word para no perder presicion
											;R1|G1|B1|R2|G2|B2|R3|G3 , cada color de 2 bytes
	movdqu xmm1, xmm0; 
	movdqu xmm2, xmm0; xmm1 y xmm2 tienen em mismo valor que xmm0
	
	psrldq xmm1, 2 ; G1|B1|R2|G2|B2|R3|G3|0
	psrldq xmm2, 4; B1|R2|G2|B2|R3|G3|0|0
	
	paddw xmm1, xmm1 ; en xmm1 ahora tengo 2*G ;G1+G1|B1+B1|R2+R2|G2+G2|B2+B2|R3+R3|G3+G3|0
	paddw xmm0, xmm1 ; en xmm0 ahora tengo R + 2*G; R1 +2G1|...|...|R2+2G2|...|...|...|0
	paddw xmm0, xmm2 ; en xmm0 ahora tengo R + 2*G + B ; R1+2G1+B1|...|...|R2+2G2+B2|...|...|...|0
	
	pand xmm0, xmm7 ; en xmm0 ahora tengo R + 2*G + B pero sin la basura que calcula de mas
									;R + 2*G + B ; R1+2G1+B1|0|0|R2+2G2+B2|0|0|0|0
	movdqu xmm1, xmm0; R1+2G1+B1|0|0|R2+2G2+B2|0|0|0|0
	psrldq xmm1, 2;XMM1= 0|0|R2+2G2+B2|0|0|0|0|0
	pand xmm0, xmm6;XMM0 = R1+2G1+B1|0|0|0|0|0|0|0
	por xmm0, xmm1;XMM0 = R1+2G1+B1|0|R2+2G2+B2|0|0|0|0
	
	psrlw xmm0, 2; XMM0 = (R1+2G1+B1)/4|0|(R2+2G2+B2)/4|0|0|0|0

	pand xmm0, xmm5 ;  ME QUEDO CON EL MINIMO ENTRE 255 Y (R1+2G1+B1)/4
	movdqu xmm1, xmm0; XMM1 = MIN((R1+2G1+B1)/4,255)|0|MIN((R2+2G2+B2)/4,255)|0|0|0|0 , como ahora cada resultado entra en un byte es equivalente a 
	psrldq xmm1, 3; XMM1 =  res1|0|0|0|res2|0|0|0|0|0|0|0|0|0|0|0
	por xmm0, xmm1; xmm0 = res1|res2|0|0|0|0|0|0|0|0|0|0|0!0
	movd eax, xmm0; al = res1, ah = res2 ,  ax = res1|res2
	mov [rsi], ax ; [rsi] = res1, [rsi+1] = res2
	add rsi, 2 ; avanzo destino en 2 pixels
	add rdi, 6 ; avanzo 2 pixels(6 bytes)
	dec r15
	cmp r15, 0
	jne cicloC

	
	cmp r13,0  
	jne proc
sigue:

	
	add rdi, r10
	add rsi, r11
	dec rcx
	cmp rcx, 0
	jne cicloF


	pop r15			;desapilo el stack
	pop r14
	pop r13
	pop r12
	pop rbx
	pop rbp
	ret

proc:
	xor r15, r15
	mov r15, r13		; muevo la cantidad que me queda por procesar x no ser multiplo de 2
	

	ciclo:
		xor rax, rax
		xor rbx, rbx

		mov al, [rdi + 1]; cargo G
		add rax, rax	 ;tengo el verde multiplicado por 2
		mov bl, [rdi]	 
		add rax, rbx
		mov bl, [rdi+2]
		add rax, rbx	 ;le sumo los dos colores que quedan
		shr ax, 2	 ;divido por 4
		cmp ax, 255	 ;saturo
	
		jle sigue2
		mov al, 255

sigue2:
	mov [rsi], al		 
	add rdi, 3
	inc rsi			
	dec r15
	cmp r15, 0
	jne ciclo	
	


	jmp sigue



